package pri.zxx.learndemo.javabase.listdemo;

import java.util.Iterator;

public class CusLinkedList<T> implements Iterable<T> {


	private Node<T> head;
	private Node<T> tail;

	public void add(T v) {
		addLast(v);
	}

	public void addFirst(T v) {
		Node<T> now = new Node<>(null, null, v);

		if (head == null) {
			head = tail = now;
		} else {
			head.prev = now;
			now.next = head;
			head = now;
		}
	}

	public void addLast(T v) {
		Node<T> now = new Node<>(null, null, v);
		if (tail == null) {
			tail = head = now;
		} else {
			tail.next = now;
			now.prev = tail;
			tail = now;
		}
	}

	public void addAfter(T v, T afterV) throws Exception {
		Node<T> aN = getNode(afterV);
		Node<T> next = aN.next;
		Node<T> now = new Node<>(aN, next, v);
		next.prev = now;
		aN.next = now;
	}

	public void add(T v, T beforeV) throws Exception {
		Node<T> beforeNode = getNode(beforeV);
		Node<T> prev = beforeNode.prev;
		Node<T> now = new Node<>(prev, beforeNode, v);
		prev.next = now;
		beforeNode.prev = now;
	}

	public void remove(T v) throws Exception {
		Node<T> node = getNode(v);
		Node<T> prev = node.prev;
		Node<T> next = node.next;

		prev.next = next;
		next.prev = prev;
		node = null;
	}

	private Node<T> getNode(T v) throws Exception {
		if (head == null) {
			throw new Exception("empty list");
		}
		Node<T> indexNodex = head;
		while (indexNodex != null) {
			if (indexNodex.value.equals(v)) {
				break;
			}
			indexNodex = indexNodex.next;
		}
		if (indexNodex == null) {
			throw new Exception("without the node beforeV");
		}
		return indexNodex;
	}

	public void recursionPr() {
		recursionPr(head);
	}

	public void recursionPr(Node<T> now) {
		if (now == null) {
			return;
		}
		T value = now.value;
		System.out.print(value + "->");
		recursionPr(now.next);
	}

	private static class Node<T> {
		private Node<T> prev;
		private Node<T> next;
		private T value;

		public Node(Node<T> prev, Node<T> next, T value) {
			this.prev = prev;
			this.next = next;
			this.value = value;
		}
	}


	@Override
	public Iterator<T> iterator() {
		return new Iterator<T>() {
			Node<T> now = head;

			@Override
			public boolean hasNext() {
				return now != null;
			}

			@Override
			public T next() {
				T value = now.value;
				now = now.next;
				return value;
			}
		};
	}

	public static void main(String[] args) throws Exception {
		CusLinkedList<Integer> cusLinkedList = new CusLinkedList<>();

		cusLinkedList.add(1);
		cusLinkedList.add(2);
		cusLinkedList.add(3);
		cusLinkedList.add(4);
		cusLinkedList.addFirst(5);
		cusLinkedList.add(6, 2);
		cusLinkedList.addAfter(7, 3);
		cusLinkedList.remove(1);
		for (Integer integer : cusLinkedList) {
			System.out.print(integer + ",");
		}
		System.out.println();
		System.out.println("---------------------");
		cusLinkedList.recursionPr();
	}
}
